﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MyBet.Web.DAL;
using System.Web.Security;
using System.Web.Profile;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Text;

namespace MyBet.Web
{
    //[DataContractAttribute(IsReference = true)]
    [Serializable()]
    public class EventObject
    {
        private int _eventId;
        private int _contestId;
        private int _dayNumber;
        private DateTime _openDate;
        private DateTime _closeDate;
        private string _displayName;
        private int _seasonId;
        private int _championshipId;

        [Key()]
        [DataMemberAttribute()]
        public int EventId
        {
            get { return _eventId; }
            set { _eventId = value; }
        }

        [DataMemberAttribute()]
        public int ContestId
        {
            get { return _contestId; }
            set { _contestId = value; }
        }

        [DataMemberAttribute()]
        public int ChampionshipId
        {
            get { return _championshipId; }
            set { _championshipId = value; }
        }

        [DataMemberAttribute()]
        public int DayNumber
        {
            get { return _dayNumber; }
            set { _dayNumber = value; }
        }

        [DataMemberAttribute()]
        public DateTime OpenDate
        {
            get { return _openDate; }
            set { _openDate = value; }
        }

        [DataMemberAttribute()]
        public DateTime CloseDate
        {
            get { return _closeDate; }
            set { _closeDate = value; }
        }

        [DataMemberAttribute()]
        public string DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }

        [DataMemberAttribute()]
        public int SeasonId
        {
            get { return _seasonId; }
            set { _seasonId = value; }
        }

        public override string ToString()
        {
            return DisplayName;
        }

        public static EventObject CopyFrom(Events d)
        {
            EventObject evt = new EventObject();
            evt.EventId = d.EventId;
            evt.ChampionshipId = d.Contests.ChampionshipId;
            evt.ContestId = d.ContestId;
            evt.DayNumber = d.DayNumber;
            evt.OpenDate = d.OpenDate;
            evt.CloseDate = d.CloseDate;
            evt.DisplayName = String.Empty;
            evt.SeasonId = d.Contests.SeasonId;
            return evt;
        }

        /// <summary>
        /// Load event object from event id
        /// </summary>
        /// <param name="eventId">championship identifier</param>
        /// <returns></returns>
        public static Events GetEventFromDatabase(MyBetDBEntities dbContext, int eventId)
        {
            var query = (from championshipday in dbContext.Events
                         where championshipday.EventId == eventId
                         select championshipday);
            IList<Events> days = query.ToList();
            if (days.Count != 1)
            {
                // day not defined
                return null;
            }
            return days[0];
        }

        /// <summary>
        /// Return championship day from database for a given championship, season and day number
        /// </summary>
        /// <param name="championshipId">championship identifier</param>
        /// <param name="seasonId">season identifier</param>
        /// <param name="dayNumber">day number</param>
        /// <returns></returns>
        public static Events GetEventFromDatabase(MyBetDBEntities dbContext, int championshipId, int seasonId, int dayNumber)
        {
            MyBetDBEntities db = dbContext;
            // Extract information from database
            if (db == null)
            {
                db = new MyBetDBEntities();
            }

            var query = (from championshipday in db.Events
                         where championshipday.DayNumber == dayNumber && championshipday.Contests.ChampionshipId == championshipId && championshipday.Contests.SeasonId == seasonId
                         select championshipday);
            IList<Events> days = query.ToList();
            if (days.Count != 1)
            {
                // day not defined
                return null;
            }
            return days[0];
        }

        /// <summary>
        /// Return all events of a given custom contest
        /// </summary>
        /// <param name="dbContext">Connection to database</param>
        /// <param name="customContestId">Custom contest identifier</param>
        /// <returns></returns>
        public static List<EventObject> GetEvents(MyBetDBEntities dbContext, int customContestId)
        {
            List<EventObject> returnList = new List<EventObject>();
            StringBuilder sql = new StringBuilder();
            sql.Append("SELECT event.EventId, contest.ContestId,  contest.ChampionshipId, contest.SeasonId, event.DayNumber, event.OpenDate, event.CloseDate ");
            sql.Append("FROM dbo.CustomContest as cc ");
            sql.Append("LEFT JOIN dbo.CustomContestLinks ccl ON ccl.CustomContestId = cc.CustomContestId ");
            sql.Append("LEFT JOIN dbo.Contests contest ON contest.ContestId = ccl.ContestId ");
            sql.Append("LEFT JOIN dbo.Events event ON event.ContestId = contest.ContestId ");
            sql.Append(String.Format("WHERE cc.CustomContestId={0} ORDER BY event.CloseDate",customContestId));
            // Get user information
            IEnumerable<EventObject> results = dbContext.ExecuteStoreQuery<EventObject>(sql.ToString());
            foreach (EventObject sqlObject in results)
            {
                returnList.Add(sqlObject);
            }

            return returnList;
        }

        public static int GetBestScore(MyBetDBEntities dbContext, int eventid)
        {
            StringBuilder sql = new StringBuilder();
            sql.Append("SELECT MAX(es.score) ");
            sql.Append("FROM dbo.EventScores es");
            sql.Append(String.Format(" WHERE es.EventId={0}", eventid));
            // Get user information
            IEnumerable<Int32?> results = dbContext.ExecuteStoreQuery<Int32?>(sql.ToString());
            if (results != null)
            {
                foreach (Int32? obj in results)
                {
                    if (obj.HasValue)
                    {
                        return obj.Value;
                    }
                    return 0;
                }
            }

            return 0;
        }

        /// <summary>
        /// Update event score
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="userId"></param>
        /// <param name="evt"></param>
        /// <returns></returns>
        public static bool AddOrUpdateScore(MyBetDBEntities dbContext, Guid userId, Events evt, Ranks rank, byte isBestScore)
        {
            var query = (from evtScore in dbContext.EventScores
                         where evtScore.EventId == evt.EventId && evtScore.UserId == userId
                         select evtScore);
            IList<EventScores> scores = query.ToList();
            if (scores.Count < 1)
            {
                // score not set
                EventScores newScore = new EventScores();
                newScore.UserId = userId;
                newScore.EventId = evt.EventId;
                newScore.Score = System.Convert.ToInt32(rank.TotalScore);
                newScore.GoodPredictionCount = System.Convert.ToInt32(rank.GoodPredictionCount);
                newScore.GoodScoreCount = System.Convert.ToInt32(rank.GoodScoreCount);
                newScore.CurrentRank = rank.CurrentRank;
                newScore.IsBestScore = isBestScore;
                dbContext.EventScores.AddObject(newScore);
            }
            else
            {
                scores[0].Score = System.Convert.ToInt32(rank.TotalScore);
                scores[0].GoodPredictionCount = System.Convert.ToInt32(rank.GoodPredictionCount);
                scores[0].GoodScoreCount = System.Convert.ToInt32(rank.GoodScoreCount);
                scores[0].CurrentRank = rank.CurrentRank;
                scores[0].IsBestScore = isBestScore;
            }

            //dbContext.SaveChanges();
            return true;
        }


        /// <summary>
        /// Add a new championship day in database
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="championshipId"></param>
        /// <param name="seasonId"></param>
        /// <param name="dayNumber"></param>
        /// <param name="openDate"></param>
        /// <param name="closeDate"></param>
        public static bool AddOrUpdate(MyBetDBEntities dbContext, Events evt, int contestId, int dayNumber, DateTime openDate, DateTime closeDate)
        {
            MyBetDBEntities db = dbContext;
            try
            {
                // Extract information from database
                if (db == null)
                {
                    db = new MyBetDBEntities();
                }
                if (evt == null)
                {
                    // Add
                    Events newEvent = new Events();
                    newEvent.ContestId = contestId;
                    newEvent.DayNumber = dayNumber;
                    newEvent.OpenDate = openDate;
                    newEvent.CloseDate = closeDate;
                    db.Events.AddObject(newEvent);
                    //dbContext.SaveChanges();
                }
                else
                {
                    // Update
                    evt.ContestId = contestId;
                    evt.DayNumber = dayNumber;
                    evt.OpenDate = openDate;
                    evt.CloseDate = closeDate;
                    //dbContext.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return false;
            }

            return true;
        }

        public static List<EventObject> GetEventList(int customContestId)
        {
            List<EventObject> events = null;
            // Ajoutez votre implémentation d'opération ici
            using (MyBetDBEntities dbContext = new MyBetDBEntities())
            {
                events = EventObject.GetEvents(dbContext, customContestId);
            }
            return events;
        }

    }
}